/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.example.clientsocket;

import ADO.Logs;
import Soporte.GestorUsuario;
import java.io.EOFException;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import javax.swing.JFrame;

/**
 *
 * @author Marco
 */
public class Servidor extends Thread {

    // va a ser el frame principal, asi hacemos que llame a los metodos que necesitamos
    Servidor.OnComunicarFrameListener principalListener;
// IMPORTANTE SI VAS A TRABAJAR CON OBJETOS, PARA QUE JAVA LOS TOME COMO IGUALES, TIENEN QUE 
    // QUE TENER LA MISMA JERARQUIA DE PAQUETES
    Socket skCliente;
    ServerSocket skServidor;
    String datareceived, substring1, substring2;
    final int PUERTO = 5555;// Puerto que utilizara el servidor utilizar este
    // mismo en el cliente
    String IP_client;
    ObjectOutputStream oos = null;
    String TimeStamp;

    public Servidor(JFrame principal) {
        principalListener = (Servidor.OnComunicarFrameListener) principal;



    }

    // en base al codigo de accion recibido realizaremos una accion
    public void Exec(int action_num) {
        String ACTNUM = null;
        String ACT1 = "vlc";// abrir VLC
        String ACT2 = "calc";// Chrome
        String ACT4 = "";

        try {
            switch (action_num) {
                case 1: {
                    ACTNUM = ACT1;
                    break;
                }
                case 2: {
                    ACTNUM = ACT2;
                    break;
                }
                case 4: {
                    ACTNUM = ACT4;
                    break;
                }
                default: {
                    System.out.println("EXEC Error invalid parameter:" + ACTNUM);
                    ACTNUM = null;

                    break;
                }
            }
            //Realizamos la accion
            Process p = Runtime.getRuntime().exec(ACTNUM);
        } catch (Exception e) {
            /* Se lanza una excepción si no se encuentra en ejecutable o el fichero no es ejecutable. */
            System.out.println("EXEC Error " + e);
        }
    }

    /*
     * Interface para comunicarnos con el frame principal
     */
    public interface OnComunicarFrameListener {

        public void onEscribirConsola(String textoAEscribir);
        // public void onDetenerServidor();
    }

    public void iniciarServidor() {
        try {
            principalListener.onEscribirConsola("************ SERVER ****************");
            skServidor = new ServerSocket(PUERTO);
            principalListener.onEscribirConsola("Escuchando en el puerto" + PUERTO);
            principalListener.onEscribirConsola("IP: " + this.obtenerIp());
            principalListener.onEscribirConsola("Esperando...");
            String extra = "";
            Mensaje peticion = null;

            TimeStamp = new java.util.Date().toString();

            try {
                // Creamos socket para manejar conexion con cliente
                skCliente = skServidor.accept(); // esperamos al cliente
                // una vez q se conecto obtenemos la ip
                IP_client = skCliente.getInetAddress().toString();
                //System.out.println("[" + TimeStamp + "] Conectado al cliente "
                //		+ "IP:" + IP_client);
                principalListener.onEscribirConsola(">Conectado al cliente "
                        + "IP:" + IP_client + "  [" + TimeStamp + "]");
                Logs gestorLog = new Logs();
                while (true) {

                    // Manejamos flujo de Entrada
                    ObjectInputStream ois = new ObjectInputStream(
                            skCliente.getInputStream());
                    if (ois != null) {
                        // Cremos un Objeto con lo recibido del cliente
                        Object objetoRecibido = ois.readObject();// leemos objeto

                        // si el objeto es una instancia de Mensaje_data
                        if (objetoRecibido instanceof Mensaje) {
                            // casteamos el objeto
                            peticion = (Mensaje) objetoRecibido;

                            // Vemos el mensaje que recibimos
                            // si  la accion no es terminar conexxion
                            if (peticion.acion != Constantes.TERMINAR_CONEXION) {

                                //Interpretamos la accion deseada
                                switch (peticion.acion) {
                                    case Constantes.INICIAR_SESSION:
                                        principalListener.onEscribirConsola("> Solicitud de inicio de Sesion");
                                        principalListener.onEscribirConsola("  Usuario: " + peticion.usuario);
                                        Respuesta rta = new Respuesta();
                                        rta.tipoRespuesta = Constantes.RESPUESTA_LOGUEO;
                                        boolean userValido = valdiarUsuario(peticion.usuario, peticion.contraseña);
                                        rta.loguinExitoso = userValido;
                                        oos = new ObjectOutputStream(skCliente.getOutputStream());
                                        oos.writeObject(rta);
                                        oos.flush();
                                        if (userValido) {
                                            principalListener.onEscribirConsola("> Bienvenido " + peticion.usuario);
                                            gestorLog.entrada(Logs.opciones.InicioSesion, Logs.MOVIL);
                                        } else {
                                            principalListener.onEscribirConsola("> Loguin incorrecto");
                                        }
                                        break;


                                    case Constantes.PEDIR_LOG_ACCIONES:
                                        Logs gestorLogo = new Logs();
                                        principalListener.onEscribirConsola("> Enviando log de acciones");
                                        Respuesta rta3 = new Respuesta();
                                        rta3.tipoRespuesta = Constantes.LOG_ACCIONES;
                                        rta3.acciones = gestorLogo.getLogsParaMovil();
                                        oos = new ObjectOutputStream(skCliente.getOutputStream());
                                        oos.writeObject(rta3);
                                        oos.flush();


                                        break;
                                    case Constantes.PEDIR_IMAGEN_CONCRETA:
                                        principalListener.onEscribirConsola("> Enviando Imagen");
                                        Respuesta rta4 = new Respuesta();
                                        rta4.tipoRespuesta = Constantes.TOMAR_IMAGEN_CONCRETA;
                                        rta4.imagen = archivoToByte(peticion.usuario);// no quera agregar mas campos
                                        oos = new ObjectOutputStream(skCliente.getOutputStream());
                                        oos.writeObject(rta4);
                                        oos.flush();
                                        gestorLog = new Logs();
                                        gestorLog.entrada(Logs.opciones.AbrirImagen, Logs.MOVIL);
                                        break;

                                    case Constantes.PEDIR_LISTADO_IMAGENES:
                                        principalListener.onEscribirConsola("> Enviando lista de imagenes");
                                        Respuesta respuesta = new Respuesta();
                                        respuesta.tipoRespuesta = Constantes.LISTADO_IMAGENES;
                                        respuesta.imagenes = Constantes.listarImagenesGuardadas();
                                        oos = new ObjectOutputStream(skCliente.getOutputStream());
                                        oos.writeObject(respuesta);
                                        oos.flush();
                                        break;

                                }


                            } else {

                                //La accion es terminar la conexion cerramos socket
                                skCliente.close();
                                ois.close();
                                principalListener.onEscribirConsola("["
                                        + TimeStamp
                                        + "] Last_msg detected Conexion cerrada, gracias vuelva pronto");
                                System.out
                                        .println("["
                                        + TimeStamp
                                        + "] Last_msg detected Conexion cerrada, gracias vuelva pronto");
                                break;
                            }
                        } else {
                            // Si no es del tipo esperado, se marca error
                            System.err.println("Mensaje no esperado ");
                        }
                    }

                }

            } catch (EOFException eof) {
                principalListener.onEscribirConsola("> El cliente: " + IP_client + " perdio la conexion");
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("[" + TimeStamp + "] Error ");
            }

        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("[" + TimeStamp + "] Error ");
        }

    }

    /* metodo para obtener nuestra ip y mostrarla en consola*/
    public String obtenerIp() {
        try {
            InetAddress localHost = InetAddress.getByName("MARCO-PC");
            return localHost.getHostAddress();
        } catch (UnknownHostException ex) {
            ex.printStackTrace();
            return "";
        }
    }

    /**
     * *****************************METODO PARA LIMPIAR CODIGO
     */////////////////////////
    public boolean valdiarUsuario(String usuario, String contraseña) {
        GestorUsuario gestor = new GestorUsuario();
        return gestor.validarUsuario(usuario, contraseña);

    }

    // este metodo recibe una direccion de arrchivo y la pasa a bytes
    public byte[] archivoToByte(String ruta) {
        byte[] bytes = null;
        try {
            String rutaCompleta = "./Saves/" + ruta;
            Path path = Paths.get("./Saves/" + ruta);
            bytes = Files.readAllBytes(path);

        } catch (IOException IOE) {
            return null;
        }
        return bytes;
    }

    public void detenerServidor() {

        try {
            skCliente.close();

        } catch (IOException IOE) {
            IOE.printStackTrace();
            principalListener.onEscribirConsola("> Servidor detenido por el usuario.");
            // principalListener.onDetenerServidor();
        }


    }
    
   
}
